package com.davemorrissey.labs.subscaleview;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpUrlConnectionNetworkImage {
    private ExecutorService mExecutorService;

    public HttpUrlConnectionNetworkImage(ExecutorService executorService) {
        mExecutorService = executorService;
    }

    public HttpUrlConnectionNetworkImage() {
        mExecutorService = Executors.newFixedThreadPool(3);
    }

    public void fetchSync(String url, HttpCallback callback) {
        mExecutorService.execute(
                new Runnable() {
                    @Override
                    public void run() {
                        HttpURLConnection connection = null;
                        InputStream is = null;
                        try {
                            connection = downloadFrom(url);
                            if (connection != null) {
                                is = connection.getInputStream();
                                callback.onResponse(is, -1);
                            }
                        } catch (IOException e) {
                            callback.onFailure(e);
                        } finally {
                            if (is != null) {
                                try {
                                    is.close();
                                } catch (IOException e) {
                                    is = null;
                                }
                            }
                            if (connection != null) {
                                connection.disconnect();
                            }
                        }
                    }
                });
    }

    private HttpURLConnection downloadFrom(String url) throws IOException {
        HttpURLConnection connection = openConnectionTo(url);
        connection.setConnectTimeout(3000);
        int responseCode = connection.getResponseCode();
        if (isHttpSuccess(responseCode)) {
            return connection;
        } else if (isHttpRedirect(responseCode)) {
            connection.disconnect();
            return null;
        } else {
            connection.disconnect();
            throw new IOException(String.format(Locale.ROOT, "Image URL %s returned HTTP code %d",
                    url.toString(), responseCode));
        }
    }

    private boolean isHttpRedirect(int responseCode) {
        switch (responseCode) {
            case HttpURLConnection.HTTP_MULT_CHOICE:
            case HttpURLConnection.HTTP_MOVED_PERM:
            case HttpURLConnection.HTTP_MOVED_TEMP:
            case HttpURLConnection.HTTP_SEE_OTHER:
                return true;
            default:
                return false;
        }
    }

    private boolean isHttpSuccess(int responseCode) {
        return (responseCode >= HttpURLConnection.HTTP_OK && responseCode < HttpURLConnection.HTTP_MULT_CHOICE);
    }

    private HttpURLConnection openConnectionTo(String urlString) throws IOException {
        URL url = new URL(urlString);
        return (HttpURLConnection) url.openConnection();
    }

    public interface HttpCallback {
        void onResponse(InputStream response, int responseLength) throws IOException;

        void onFailure(Throwable throwable);

        void onCancellation();
    }
}
